/**
 * 自定义提取器注册表
 */

import type { CustomExtractor, FileInfo, MetadataPattern } from '../types';
import fs from 'fs';
import path from 'path';
import { ElfAnalyzer } from '../../elf/elf_analyzer';

/**
 * 自定义提取器注册表（单例）
 */
export class CustomExtractorRegistry {
    private static instance: CustomExtractorRegistry | null = null;
    private extractors: Map<string, CustomExtractor>;

    private constructor() {
        this.extractors = new Map();
        this.registerBuiltinExtractors();
    }

    /**
     * 获取单例实例
     */
    public static getInstance(): CustomExtractorRegistry {
        CustomExtractorRegistry.instance ??= new CustomExtractorRegistry();
        return CustomExtractorRegistry.instance;
    }

    /**
     * 注册提取器
     */
    public register(name: string, extractor: CustomExtractor): void {
        this.extractors.set(name, extractor);
    }

    /**
     * 获取提取器
     */
    public get(name: string): CustomExtractor | undefined {
        return this.extractors.get(name);
    }

    /**
     * 注册内置提取器
     */
    private registerBuiltinExtractors(): void {
        // Flutter Dart 包提取器
        this.register('extractDartPackages', extractDartPackages);

        // Flutter 版本提取器
        this.register('extractFlutterVersion', extractFlutterVersion);
        this.register('extractFlutterHex40', extractFlutterHex40);
        this.register('extractFlutterVersionLastModified', extractFlutterVersionLastModified);
        this.register('extractDartVersion', extractDartVersion);

        // KMP Kotlin 签名提取器
        this.register('extractKotlinSignatures', extractKotlinSignatures);

        // 文件元数据提取器
        this.register('extractLastModified', extractLastModified);

        // SO文件信息提取器
        this.register('extractSoDependencies', extractSoDependencies);
        this.register('extractSoExports', extractSoExports);
        this.register('extractSoImports', extractSoImports);
    }
}

/**
 * 提取 Dart 包（从 libapp.so）
 * 原始逻辑来自 FlutterAnalyzer.analyzeDartPackages
 *
 * 注意：这个方法返回的是 pub.dev 上的开源包（排除自研包），包含版本号
 */
async function extractDartPackages(fileInfo: FileInfo, _pattern?: MetadataPattern): Promise<Array<string>> {
    if (!fileInfo.content) {
        return [];
    }

    try {
        // 使用 ELF 分析器提取字符串
        const elfAnalyzer = ElfAnalyzer.getInstance();

        // 创建临时文件
        const tempDir = path.join(process.cwd(), '.temp');
        if (!fs.existsSync(tempDir)) {
            fs.mkdirSync(tempDir, { recursive: true });
        }

        const tempFilePath = path.join(tempDir, `temp_${Date.now()}.so`);
        fs.writeFileSync(tempFilePath, fileInfo.content);

        try {
            const strings = await elfAnalyzer.strings(tempFilePath);

            // 匹配 package 字符串的正则表达式（支持版本号）
            const packageRegex = /package:([a-zA-Z0-9_]+)(?:@([0-9]+\.[0-9]+\.[0-9]+))?/g;
            const packagesMap = new Map<string, string>(); // packageName -> version (or empty)

            for (const str of strings) {
                let match;
                while ((match = packageRegex.exec(str)) !== null) {
                    const packageName = match[1];
                    const version = match[2] || ''; // 版本号可能不存在

                    // 如果已经有这个包，优先保留有版本号的
                    const existing = packagesMap.get(packageName);
                    if (!existing || (version && !existing)) {
                        packagesMap.set(packageName, version);
                    }
                }
            }

            // 加载 pub.dev 包列表，只保留开源包
            try {
                // 使用与 loadFrameworkConfig 相同的路径查找策略
                // 先尝试从当前工作目录查找（适用于 ts-node 运行）
                let resPath = path.join(process.cwd(), 'res/techstack/pub_dev_packages.json');

                // 如果找不到，尝试从编译后的目录查找（适用于编译后运行）
                if (!fs.existsSync(resPath)) {
                    let resDir = path.join(__dirname, 'res');
                    if (!fs.existsSync(resDir)) {
                        resDir = path.join(__dirname, '../../../../res');
                    }
                    resPath = path.join(resDir, 'techstack/pub_dev_packages.json');
                }

                const data = fs.readFileSync(resPath, 'utf-8');
                const jsonData = JSON.parse(data) as { packages: Array<string> };
                const pubDevPackages = new Set(jsonData.packages);

                // 只保留在 pub.dev 上的包（开源包），排除自研包
                const openSourcePackages: Array<string> = [];
                for (const [packageName, version] of packagesMap.entries()) {
                    if (pubDevPackages.has(packageName)) {
                        // 如果有版本号，格式为 "packageName@version"，否则只显示包名
                        openSourcePackages.push(version ? `${packageName}@${version}` : packageName);
                    }
                }
                return openSourcePackages;
            } catch (error) {
                console.warn('Failed to load pub.dev packages, returning all packages:', error);
                // 返回所有包（带版本号）
                const allPackages: Array<string> = [];
                for (const [packageName, version] of packagesMap.entries()) {
                    allPackages.push(version ? `${packageName}@${version}` : packageName);
                }
                return allPackages;
            }
        } finally {
            // 清理临时文件
            if (fs.existsSync(tempFilePath)) {
                fs.unlinkSync(tempFilePath);
            }
        }
    } catch (error) {
        console.warn('Failed to extract Dart packages:', error);
        return [];
    }
}

/**
 * 提取 Dart 版本（从 libflutter.so）
 * 原始逻辑：从 strings 中匹配 Dart 版本字符串
 * 注意：这个方法实际上提取的是 Dart 版本，不是 Flutter 版本
 */
async function extractFlutterVersion(fileInfo: FileInfo, _pattern?: MetadataPattern): Promise<string | null> {
    if (!fileInfo.content) {
        return null;
    }

    try {
        // 使用 ELF 分析器提取字符串
        const elfAnalyzer = ElfAnalyzer.getInstance();

        // 创建临时文件
        const tempDir = path.join(process.cwd(), '.temp');
        if (!fs.existsSync(tempDir)) {
            fs.mkdirSync(tempDir, { recursive: true });
        }

        const tempFilePath = path.join(tempDir, `temp_${Date.now()}.so`);
        fs.writeFileSync(tempFilePath, fileInfo.content);

        try {
            const strings = await elfAnalyzer.strings(tempFilePath);

            // 匹配 Dart 版本字符串（格式：2.19.6 (stable)）
            const dartVersionRegex = /^(\d+\.\d+\.\d+) \(stable\)/;

            for (const str of strings) {
                const match = str.match(dartVersionRegex);
                if (match) {
                    return match[1]; // 返回版本号部分，如 "2.19.6"
                }
            }

            return null;
        } finally {
            // 清理临时文件
            if (fs.existsSync(tempFilePath)) {
                fs.unlinkSync(tempFilePath);
            }
        }
    } catch (error) {
        console.warn('Failed to extract Dart version:', error);
        return null;
    }
}

/**
 * 提取 Kotlin 签名（使用 ELF 分析器）
 */
async function extractKotlinSignatures(fileInfo: FileInfo, _pattern?: MetadataPattern): Promise<Array<string>> {
    if (!fileInfo.content) {
        return [];
    }

    try {
        // 使用 ELF 分析器提取字符串
        const elfAnalyzer = ElfAnalyzer.getInstance();

        // 创建临时文件
        const tempDir = path.join(process.cwd(), '.temp');
        if (!fs.existsSync(tempDir)) {
            fs.mkdirSync(tempDir, { recursive: true });
        }

        const tempFilePath = path.join(tempDir, `temp_kmp_${Date.now()}.so`);
        fs.writeFileSync(tempFilePath, fileInfo.content);

        try {
            const strings = await elfAnalyzer.strings(tempFilePath);

            const signatures = new Set<string>();
            const kotlinPatterns = ['kfun:', 'Kotlin', 'kotlin', 'KOTLIN_NATIVE'];

            for (const str of strings) {
                for (const pattern of kotlinPatterns) {
                    if (str.includes(pattern)) {
                        signatures.add(pattern);
                    }
                }
            }

            return Array.from(signatures);
        } finally {
            // 清理临时文件
            if (fs.existsSync(tempFilePath)) {
                fs.unlinkSync(tempFilePath);
            }
        }
    } catch (error) {
        console.warn('Failed to extract Kotlin signatures:', error);
        return [];
    }
}

/**
 * 提取 Flutter 40位 Hex 字符串（从 libflutter.so）
 */
async function extractFlutterHex40(fileInfo: FileInfo, _pattern?: MetadataPattern): Promise<string | null> {
    if (!fileInfo.content) {
        return null;
    }

    try {
        // 使用 ELF 分析器提取字符串
        const elfAnalyzer = ElfAnalyzer.getInstance();

        // 创建临时文件
        const tempDir = path.join(process.cwd(), '.temp');
        if (!fs.existsSync(tempDir)) {
            fs.mkdirSync(tempDir, { recursive: true });
        }

        const tempFilePath = path.join(tempDir, `temp_hex_${Date.now()}.so`);
        fs.writeFileSync(tempFilePath, fileInfo.content);

        try {
            const strings = await elfAnalyzer.strings(tempFilePath);

            // 匹配 40 位 Hex 字符串的正则表达式
            const hex40Regex = /^[0-9a-fA-F]{40}$/;
            const hex40Strings: Array<string> = [];

            // 收集所有 40 位 hex 字符串
            for (const str of strings) {
                if (hex40Regex.test(str)) {
                    hex40Strings.push(str);
                }
            }

            if (hex40Strings.length === 0) {
                return null;
            }

            // 加载 Flutter 版本映射
            const flutterVersions = await getFlutterVersions();

            // 找到匹配的版本
            for (const hex40 of hex40Strings) {
                const versionInfo = flutterVersions.get(hex40);
                if (versionInfo) {
                    // 找到匹配的版本，返回 hex40
                    return hex40;
                }
            }

            // 如果没有找到匹配的版本，返回第一个 hex40 字符串
            return hex40Strings[0];
        } finally {
            // 清理临时文件
            if (fs.existsSync(tempFilePath)) {
                fs.unlinkSync(tempFilePath);
            }
        }
    } catch (error) {
        console.warn('Failed to extract Flutter hex40:', error);
        return null;
    }
}

/**
 * 获取 Flutter 版本映射
 * 从 res/techstack/flutter_versions.json 加载
 */
async function getFlutterVersions(): Promise<Map<string, { lastModified: string }>> {
    try {
        // 使用与 loadFrameworkConfig 相同的路径查找策略
        // 先尝试从当前工作目录查找（适用于 ts-node 运行）
        let resPath = path.join(process.cwd(), 'res/techstack/flutter_versions.json');

        // 如果找不到，尝试从编译后的目录查找（适用于编译后运行）
        if (!fs.existsSync(resPath)) {
            let resDir = path.join(__dirname, 'res');
            if (!fs.existsSync(resDir)) {
                resDir = path.join(__dirname, '../../../../res');
            }
            resPath = path.join(resDir, 'techstack/flutter_versions.json');
        }

        if (fs.existsSync(resPath)) {
            const data = fs.readFileSync(resPath, 'utf-8');
            const versionsData = JSON.parse(data) as Record<string, { lastModified: string }>;
            const versions = new Map<string, { lastModified: string }>();

            for (const [hex40, info] of Object.entries(versionsData)) {
                versions.set(hex40, info);
            }

            return versions;
        } else {
            console.warn('flutter_versions.json not found in res/techstack directory, using empty map');
            return new Map();
        }
    } catch (error) {
        console.warn('Failed to load Flutter versions from local file:', error);
        return new Map();
    }
}

/**
 * 提取 Flutter 版本的最后修改时间
 * 从 flutter_versions.json 中根据 hex40 查找对应的 lastModified
 */
async function extractFlutterVersionLastModified(fileInfo: FileInfo, _pattern?: MetadataPattern): Promise<string | null> {
    // 首先提取 hex40
    const hex40 = await extractFlutterHex40(fileInfo);
    if (!hex40) {
        return null;
    }

    try {
        // 加载 Flutter 版本映射
        const flutterVersions = await getFlutterVersions();
        const versionInfo = flutterVersions.get(hex40);

        if (versionInfo?.lastModified) {
            return versionInfo.lastModified;
        }

        return null;
    } catch (error) {
        console.warn('Failed to extract Flutter version lastModified:', error);
        return null;
    }
}

/**
 * 提取 Dart 版本（从 libflutter.so）
 */
async function extractDartVersion(fileInfo: FileInfo, _pattern?: MetadataPattern): Promise<string | null> {
    // 复用 extractFlutterVersion
    return extractFlutterVersion(fileInfo);
}

/**
 * 提取文件最后修改时间
 */
async function extractLastModified(fileInfo: FileInfo, _pattern?: MetadataPattern): Promise<string | null> {
    if (!fileInfo.lastModified) {
        return null;
    }

    // 返回 ISO 格式的时间字符串
    return fileInfo.lastModified.toISOString();
}

/**
 * SO文件ELF信息缓存（基于文件路径）
 * 避免同一个文件被多次解析
 */
const soElfInfoCache = new Map<string, Promise<{ dependencies: Array<string>; exports: Array<string>; imports: Array<string> } | null>>();

/**
 * 统一获取SO文件的ELF信息（带缓存）
 * 合并了 extractSoDependencies、extractSoExports 和 extractSoImports 的公共逻辑
 */
async function getSoElfInfo(fileInfo: FileInfo): Promise<{ dependencies: Array<string>; exports: Array<string>; imports: Array<string> } | null> {
    if (!fileInfo.content) {
        return null;
    }

    // 检查文件是否为SO文件
    if (!fileInfo.file.endsWith('.so')) {
        return null;
    }

    // 使用文件路径作为缓存键
    const cacheKey = fileInfo.file;

    // 如果缓存中存在，直接返回
    if (soElfInfoCache.has(cacheKey)) {
        return soElfInfoCache.get(cacheKey)!;
    }

    // 创建解析任务
    const parseTask = (async () => {
        // 再次检查 content（TypeScript 类型保护）
        if (!fileInfo.content) {
            return null;
        }

        try {
            const elfAnalyzer = ElfAnalyzer.getInstance();

            // 创建临时文件
            const tempDir = path.join(process.cwd(), '.temp');
            if (!fs.existsSync(tempDir)) {
                fs.mkdirSync(tempDir, { recursive: true });
            }

            const tempFilePath = path.join(tempDir, `temp_so_${Date.now()}_${path.basename(fileInfo.file)}`);
            fs.writeFileSync(tempFilePath, fileInfo.content);

            try {
                const elfInfo = await elfAnalyzer.getElfInfo(tempFilePath);
                return {
                    dependencies: elfInfo.dependencies,
                    exports: elfInfo.exports,
                    imports: elfInfo.imports
                };
            } finally {
                // 清理临时文件
                if (fs.existsSync(tempFilePath)) {
                    fs.unlinkSync(tempFilePath);
                }
            }
        } catch (error) {
            console.warn(`Failed to extract SO info from ${fileInfo.file}:`, error);
            return null;
        }
    })();

    // 将任务加入缓存
    soElfInfoCache.set(cacheKey, parseTask);

    // 解析完成后，可以选择保留缓存或清理（这里保留缓存以提高性能）
    return parseTask;
}

/**
 * 提取SO文件的依赖库列表
 */
async function extractSoDependencies(fileInfo: FileInfo, _pattern?: MetadataPattern): Promise<Array<string>> {
    const elfInfo = await getSoElfInfo(fileInfo);
    return elfInfo?.dependencies ?? [];
}

/**
 * 提取SO文件的导出符号（限制数量以避免过大）
 */
async function extractSoExports(fileInfo: FileInfo, _pattern?: MetadataPattern): Promise<Array<string>> {
    const elfInfo = await getSoElfInfo(fileInfo);
    return elfInfo?.exports ?? [];
}

/**
 * 提取SO文件的导入符号（限制数量以避免过大）
 */
async function extractSoImports(fileInfo: FileInfo, _pattern?: MetadataPattern): Promise<Array<string>> {
    const elfInfo = await getSoElfInfo(fileInfo);
    return elfInfo?.imports ?? [];
}

